home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ftp / new / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-27  |  8.9 KB  |  511 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)main.c    5.13 (Berkeley) 3/14/89";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  * FTP User Program -- Command Interface.
  30.  */
  31. #include "ftp_var.h"
  32. #include <sys/socket.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/types.h>
  35.  
  36. #include <arpa/ftp.h>
  37.  
  38. #include <signal.h>
  39. #include <stdio.h>
  40. #include <errno.h>
  41. #include <ctype.h>
  42. #include <netdb.h>
  43. #include <pwd.h>
  44.  
  45.  
  46. uid_t    getuid();
  47. int    intr();
  48. int    lostpeer();
  49. extern    char *home;
  50. char    *getlogin();
  51.  
  52. main(argc, argv)
  53.     char *argv[];
  54. {
  55.     register char *cp;
  56.     int top;
  57.     struct passwd *pw = NULL;
  58.     char homedir[MAXPATHLEN];
  59.  
  60.     sp = getservbyname("ftp", "tcp");
  61.     if (sp == 0) {
  62.         fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
  63.         exit(1);
  64.     }
  65.     doglob = 1;
  66.     interactive = 1;
  67.     autologin = 1;
  68.     argc--, argv++;
  69.     while (argc > 0 && **argv == '-') {
  70.         for (cp = *argv + 1; *cp; cp++)
  71.             switch (*cp) {
  72.  
  73.             case 'd':
  74.                 options |= SO_DEBUG;
  75.                 debug++;
  76.                 break;
  77.             
  78.             case 'v':
  79.                 verbose++;
  80.                 break;
  81.  
  82.             case 't':
  83.                 trace++;
  84.                 break;
  85.  
  86.             case 'i':
  87.                 interactive = 0;
  88.                 break;
  89.  
  90.             case 'n':
  91.                 autologin = 0;
  92.                 break;
  93.  
  94.             case 'g':
  95.                 doglob = 0;
  96.                 break;
  97.  
  98.             default:
  99.                 fprintf(stdout,
  100.                   "ftp: %c: unknown option\n", *cp);
  101.                 exit(1);
  102.             }
  103.         argc--, argv++;
  104.     }
  105.     fromatty = isatty(fileno(stdin));
  106.     /*
  107.      * Set up defaults for FTP.
  108.      */
  109.     (void) strcpy(typename, "ascii"), type = TYPE_A;
  110.     (void) strcpy(formname, "non-print"), form = FORM_N;
  111.     (void) strcpy(modename, "stream"), mode = MODE_S;
  112.     (void) strcpy(structname, "file"), stru = STRU_F;
  113.     (void) strcpy(bytename, "8"), bytesize = 8;
  114.     if (fromatty)
  115.         verbose++;
  116.     cpend = 0;           /* no pending replies */
  117.     proxy = 0;    /* proxy not active */
  118.     crflag = 1;    /* strip c.r. on ascii gets */
  119.     /*
  120.      * Set up the home directory in case we're globbing.
  121.      */
  122.     cp = getlogin();
  123.     if (cp != NULL) {
  124.         pw = getpwnam(cp);
  125.     }
  126.     if (pw == NULL)
  127.         pw = getpwuid(getuid());
  128.     if (pw != NULL) {
  129.         home = homedir;
  130.         (void) strcpy(home, pw->pw_dir);
  131.     }
  132.     if (argc > 0) {
  133.         if (setjmp(toplevel))
  134.             exit(0);
  135.         (void) signal(SIGINT, intr);
  136.         (void) signal(SIGPIPE, lostpeer);
  137.         setpeer(argc + 1, argv - 1);
  138.     }
  139.     top = setjmp(toplevel) == 0;
  140.     if (top) {
  141.         (void) signal(SIGINT, intr);
  142.         (void) signal(SIGPIPE, lostpeer);
  143.     }
  144.     for (;;) {
  145.         cmdscanner(top);
  146.         top = 1;
  147.     }
  148. }
  149.  
  150. intr()
  151. {
  152.  
  153.     longjmp(toplevel, 1);
  154. }
  155.  
  156. lostpeer()
  157. {
  158.     extern FILE *cout;
  159.     extern int data;
  160.  
  161.     if (connected) {
  162.         if (cout != NULL) {
  163.             (void) shutdown(fileno(cout), 1+1);
  164.             (void) fclose(cout);
  165.             cout = NULL;
  166.         }
  167.         if (data >= 0) {
  168.             (void) shutdown(data, 1+1);
  169.             (void) close(data);
  170.             data = -1;
  171.         }
  172.         connected = 0;
  173.     }
  174.     pswitch(1);
  175.     if (connected) {
  176.         if (cout != NULL) {
  177.             (void) shutdown(fileno(cout), 1+1);
  178.             (void) fclose(cout);
  179.             cout = NULL;
  180.         }
  181.         connected = 0;
  182.     }
  183.     proxflag = 0;
  184.     pswitch(0);
  185. }
  186.  
  187. /*char *
  188. tail(filename)
  189.     char *filename;
  190. {
  191.     register char *s;
  192.     
  193.     while (*filename) {
  194.         s = rindex(filename, '/');
  195.         if (s == NULL)
  196.             break;
  197.         if (s[1])
  198.             return (s + 1);
  199.         *s = '\0';
  200.     }
  201.     return (filename);
  202. }
  203. */
  204. /*
  205.  * Command parser.
  206.  */
  207. cmdscanner(top)
  208.     int top;
  209. {
  210.     register struct cmd *c;
  211.     struct cmd *getcmd();
  212.     extern int help();
  213.  
  214.     if (!top)
  215.         (void) putchar('\n');
  216.     for (;;) {
  217.         if (fromatty) {
  218.             printf("ftp> ");
  219.             (void) fflush(stdout);
  220.         }
  221.         if (gets(line) == 0) {
  222.             if (feof(stdin) || ferror(stdin))
  223.                 quit();
  224.             break;
  225.         }
  226.         if (line[0] == 0)
  227.             break;
  228.         makeargv();
  229.         if (margc == 0) {
  230.             continue;
  231.         }
  232.         c = getcmd(margv[0]);
  233.         if (c == (struct cmd *)-1) {
  234.             printf("?Ambiguous command\n");
  235.             continue;
  236.         }
  237.         if (c == 0) {
  238.             printf("?Invalid command\n");
  239.             continue;
  240.         }
  241.         if (c->c_conn && !connected) {
  242.             printf ("Not connected.\n");
  243.             continue;
  244.         }
  245.         (*c->c_handler)(margc, margv);
  246.         if (bell && c->c_bell)
  247.             (void) putchar('\007');
  248.         if (c->c_handler != help)
  249.             break;
  250.     }
  251.     (void) signal(SIGINT, intr);
  252.     (void) signal(SIGPIPE, lostpeer);
  253. }
  254.  
  255. struct cmd *
  256. getcmd(name)
  257.     register char *name;
  258. {
  259.     extern struct cmd cmdtab[];
  260.     register char *p, *q;
  261.     register struct cmd *c, *found;
  262.     register int nmatches, longest;
  263.  
  264.     longest = 0;
  265.     nmatches = 0;
  266.     found = 0;
  267.     for (c = cmdtab; p = c->c_name; c++) {
  268.         for (q = name; *q == *p++; q++)
  269.             if (*q == 0)        /* exact match? */
  270.                 return (c);
  271.         if (!*q) {            /* the name was a prefix */
  272.             if (q - name > longest) {
  273.                 longest = q - name;
  274.                 nmatches = 1;
  275.                 found = c;
  276.             } else if (q - name == longest)
  277.                 nmatches++;
  278.         }
  279.     }
  280.     if (nmatches > 1)
  281.         return ((struct cmd *)-1);
  282.     return (found);
  283. }
  284.  
  285. /*
  286.  * Slice a string up into argc/argv.
  287.  */
  288.  
  289. int slrflag;
  290.  
  291. makeargv()
  292. {
  293.     char **argp;
  294.     char *slurpstring();
  295.  
  296.     margc = 0;
  297.     argp = margv;
  298.     stringbase = line;        /* scan from first of buffer */
  299.     argbase = argbuf;        /* store from first of buffer */
  300.     slrflag = 0;
  301.     while (*argp++ = slurpstring())
  302.         margc++;
  303. }
  304.  
  305. /*
  306.  * Parse string into argbuf;
  307.  * implemented with FSM to
  308.  * handle quoting and strings
  309.  */
  310. char *
  311. slurpstring()
  312. {
  313.     int got_one = 0;
  314.     register char *sb = stringbase;
  315.     register char *ap = argbase;
  316.     char *tmp = argbase;        /* will return this if token found */
  317.  
  318.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  319.         switch (slrflag) {    /* and $ as token for macro invoke */
  320.             case 0:
  321.                 slrflag++;
  322.                 stringbase++;
  323.                 return ((*sb == '!') ? "!" : "$");
  324.                 /* NOTREACHED */
  325.             case 1:
  326.                 slrflag++;
  327.                 altarg = stringbase;
  328.                 break;
  329.             default:
  330.                 break;
  331.         }
  332.     }
  333.  
  334. S0:
  335.     switch (*sb) {
  336.  
  337.     case '\0':
  338.         goto OUT;
  339.  
  340.     case ' ':
  341.     case '\t':
  342.         sb++; goto S0;
  343.  
  344.     default:
  345.         switch (slrflag) {
  346.             case 0:
  347.                 slrflag++;
  348.                 break;
  349.             case 1:
  350.                 slrflag++;
  351.                 altarg = sb;
  352.                 break;
  353.             default:
  354.                 break;
  355.         }
  356.         goto S1;
  357.     }
  358.  
  359. S1:
  360.     switch (*sb) {
  361.  
  362.     case ' ':
  363.     case '\t':
  364.     case '\0':
  365.         goto OUT;    /* end of token */
  366.  
  367.     case '\\':
  368.         sb++; goto S2;    /* slurp next character */
  369.  
  370.     case '"':
  371.         sb++; goto S3;    /* slurp quoted string */
  372.  
  373.     default:
  374.         *ap++ = *sb++;    /* add character to token */
  375.         got_one = 1;
  376.         goto S1;
  377.     }
  378.  
  379. S2:
  380.     switch (*sb) {
  381.  
  382.     case '\0':
  383.         goto OUT;
  384.  
  385.     default:
  386.         *ap++ = *sb++;
  387.         got_one = 1;
  388.         goto S1;
  389.     }
  390.  
  391. S3:
  392.     switch (*sb) {
  393.  
  394.     case '\0':
  395.         goto OUT;
  396.  
  397.     case '"':
  398.         sb++; goto S1;
  399.  
  400.     default:
  401.         *ap++ = *sb++;
  402.         got_one = 1;
  403.         goto S3;
  404.     }
  405.  
  406. OUT:
  407.     if (got_one)
  408.         *ap++ = '\0';
  409.     argbase = ap;            /* update storage pointer */
  410.     stringbase = sb;        /* update scan pointer */
  411.     if (got_one) {
  412.         return(tmp);
  413.     }
  414.     switch (slrflag) {
  415.         case 0:
  416.             slrflag++;
  417.             break;
  418.         case 1:
  419.             slrflag++;
  420.             altarg = (char *) 0;
  421.             break;
  422.         default:
  423.             break;
  424.     }
  425.     return((char *)0);
  426. }
  427.  
  428. #define HELPINDENT (sizeof ("directory"))
  429.  
  430. /*
  431.  * Help command.
  432.  * Call each command handler with argc == 0 and argv[0] == name.
  433.  */
  434. help(argc, argv)
  435.     int argc;
  436.     char *argv[];
  437. {
  438.     extern struct cmd cmdtab[];
  439.     register struct cmd *c;
  440.  
  441.     if (argc == 1) {
  442.         register int i, j, w, k;
  443.         int columns, width = 0, lines;
  444.         extern int NCMDS;
  445.  
  446.         printf("Commands may be abbreviated.  Commands are:\n\n");
  447.         for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
  448.             int len = strlen(c->c_name);
  449.  
  450.             if (len > width)
  451.                 width = len;
  452.         }
  453.         width = (width + 8) &~ 7;
  454.         columns = 80 / width;
  455.         if (columns == 0)
  456.             columns = 1;
  457.         lines = (NCMDS + columns - 1) / columns;
  458.         for (i = 0; i < lines; i++) {
  459.             for (j = 0; j < columns; j++) {
  460.                 c = cmdtab + j * lines + i;
  461.                 if (c->c_name && (!proxy || c->c_proxy)) {
  462.                     printf("%s", c->c_name);
  463.                 }
  464.                 else if (c->c_name) {
  465.                     for (k=0; k < strlen(c->c_name); k++) {
  466.                         (void) putchar(' ');
  467.                     }
  468.                 }
  469.                 if (c + lines >= &cmdtab[NCMDS]) {
  470.                     printf("\n");
  471.                     break;
  472.                 }
  473.                 w = strlen(c->c_name);
  474.                 while (w < width) {
  475.                     w = (w + 8) &~ 7;
  476.                     (void) putchar('\t');
  477.                 }
  478.             }
  479.         }
  480.         return;
  481.     }
  482.     while (--argc > 0) {
  483.         register char *arg;
  484.         arg = *++argv;
  485.         c = getcmd(arg);
  486.         if (c == (struct cmd *)-1)
  487.             printf("?Ambiguous help command %s\n", arg);
  488.         else if (c == (struct cmd *)0)
  489.             printf("?Invalid help command %s\n", arg);
  490.         else
  491.             printf("%-*s\t%s\n", HELPINDENT,
  492.                 c->c_name, c->c_help);
  493.     }
  494. }
  495.  
  496. /*
  497.  * Call routine with argc, argv set from args (terminated by 0).
  498.  */
  499. /*VARARGS1*/
  500. call(routine, args)
  501.     int (*routine)();
  502.     int args;
  503. {
  504.     register int *argp;
  505.     register int argc;
  506.  
  507.     for (argc = 0, argp = &args; *argp++ != 0; argc++)
  508.         ;
  509.     (*routine)(argc, &args);
  510. }
  511.